package chapter14.Map;

import javax.swing.tree.TreeNode;
import java.util.HashMap;

/**
 * @Auther: Tx
 * @Date: 2022/5/19 20:47
 */

//解读HashMap源码
//    1.
@SuppressWarnings("all")
public class HashMapSource01 {
    public static void main(String[] args) {
        HashMap hashMap = new HashMap();
//        1.执行构造器，初始化加载因子
//        public HashMap() {
//        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
//    }
//        HashMap$Node[] table = null;

        hashMap.put("java",10);
//        2.执行put方法，Key = "java" value="10"
//        3.通过key计算hash值，并作为Putval()的参数
//
//        （hash方法）
//        static final int hash(Object key) {
//        int h;
//        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
//    }

//        4.执行PutVal()方法，在其中执行resize()方法，第一次初始化table大小为为16.
//        在PutVal的方法的最后还会判断当前的表中元素是否已经达到了，临界值。如果到达，就会再次执行resize()方法

//        final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
//        boolean evict) {
//            HashMap.Node<K,V>[] tab; HashMap.Node<K,V> p; int n, i;//赋值变量
//            if ((tab = table) == null || (n = tab.length) == 0)//如果底层的table数组为null，或长度为0，则扩容
//                n = (tab = resize()).length;
        //如果hash值对应的数组下标中的元素为空，则新建一个newNode，并把对应参数传入构造器。并将该节点，装载到table中。
//            if ((p = tab[i = (n - 1) & hash]) == null)
//                tab[i] = newNode(hash, key, value, null);
//            else {
//                HashMap.Node<K,V> e; K k;
//                if (p.hash == hash &&
//                        ((k = p.key) == key || (key != null && key.equals(k))))
//                //如果对应的hash值相同，并且key也相同(这里是防止冲突)指向同一个对象，或者equals返回真。就认为不能添加新的k-v
//                    e = p;
//                else if (p instanceof TreeNode)//如果当前的table已有的Node 是红黑树，就按照红黑树的逻辑进行处理。
//                    e = ((HashMap.TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
//                else {
//                    for (int binCount = 0; ; ++binCount) {
//                        if ((e = p.next) == null) {
//                            p.next = newNode(hash, key, value, null);
//                            if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
//                                treeifyBin(tab, hash);
//                 树化，但不是立即树化。treeifyBin()方法内还有条件。判断当前的table是否小于最小树化长度，如果是就在扩容。
//                            break;
//                        }
//                        if (e.hash == hash &&
//                                ((k = e.key) == key || (key != null && key.equals(k))))//在循环比较中，如果存在相同的就break；
//                            break;
//                        p = e;
//                    }
//                }
//                if (e != null) { // existing mapping for key
//                    V oldValue = e.value;
//                    if (!onlyIfAbsent || oldValue == null)
//                        e.value = value;
//                    afterNodeAccess(e);
//                    return oldValue;
//                }
//            }
//            ++modCount;
//            if (++size > threshold)
//                resize();
//            afterNodeInsertion(evict);
//            return null;
//        }
        hashMap.put("php",10);
//        方法同上，如果对应下标中的元素为空就会new newNode(),将数据装载进去。
        hashMap.put("java",20);//替换机制
//        （重点）：如何实现替换
//        1.此时已经不满足，对应hash值得元素为空，故走另一个分支。
//        2. 替换部分代码，并且此代码块中有return 就不会  ++modCount;，
//        if (e != null) { // existing mapping for key
//                V oldValue = e.value;
//                if (!onlyIfAbsent || oldValue == null)
//                    e.value = value;//值替换
//                afterNodeAccess(e);
//                return oldValue;
        System.out.println("hashmap="+hashMap);
    }
}
